package com.kamistoat.ruoyi.ruoyimodulessystem.controller;

import java.util.*;
import java.util.stream.Collectors;

import com.kamistoat.ruoyi.ruoyiapisystem.domain.SysDept;
import com.kamistoat.ruoyi.ruoyiapisystem.entity.SysDeptEntity;
import com.kamistoat.ruoyi.ruoyicommoncore.constant.UserConstants;
import com.kamistoat.ruoyi.ruoyicommoncore.utils.StringUtils;
import com.kamistoat.ruoyi.ruoyicommoncore.web.controller.BaseController;
import com.kamistoat.ruoyi.ruoyicommoncore.web.domain.AjaxResult;
import com.kamistoat.ruoyi.ruoyicommondatascope.annotation.DataScope;
import com.kamistoat.ruoyi.ruoyicommonlog.annotation.Log;
import com.kamistoat.ruoyi.ruoyicommonlog.enums.BusinessType;
import com.kamistoat.ruoyi.ruoyicommonsecurity.annotation.RequiresPermissions;
import com.kamistoat.ruoyi.ruoyicommonsecurity.utils.SecurityUtils;
import com.kamistoat.ruoyi.ruoyimodulessystem.service.SysDeptService;
import com.kamistoat.ruoyi.ruoyimodulessystem.vo.TreeSelect;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;


/**
 * 部门表
 *
 * @author kamistoat
 * @email linjianshanke@163.com
 * @date 2022-08-09 10:34:46
 */
@RestController
@RequestMapping("/dept")
public class SysDeptController extends BaseController {
    @Autowired
    private SysDeptService sysDeptService;

    /**
     * 匹配列表.
     *
     * @DataScope注解说明限制访问权限
     */
    @RequiresPermissions("system:dept:list")
    @RequestMapping("/list")
    @DataScope
    public AjaxResult list(SysDept sysDept) {
        List<SysDeptEntity> sysDeptEntityList = sysDeptService.selectDeptList(
                StringUtils.isNull(sysDept) ? new SysDept() : sysDept);
        return AjaxResult.success(entity2Vo(sysDeptEntityList));
    }

    /**
     * 给定一个 部门id，获取除了这个部门及其子部门之外的其他部门
     */
    @RequiresPermissions("system:dept:list")
    @RequestMapping("/list/exclude/{deptId}")
    @DataScope
    public AjaxResult excludeChild(@PathVariable(value = "deptId", required = false) Long deptId) {
        List<SysDeptEntity> sysDeptEntityList = sysDeptService.selectDeptList(new SysDept());
        // TODO 使用迭代器处理，系统提示可以直接简化为以下lambda

//        Iterator<SysDeptEntity> deptEntityIterator = sysDeptEntityList.iterator();
//        while (deptEntityIterator.hasNext()) {
//            SysDeptEntity deptEntity = deptEntityIterator.next();
//            if (deptEntity.getDeptId().equals(deptId)
//                    || ArrayUtils.contains(StringUtils.split(deptEntity.getAncestors(), ","), deptId.toString())) {
//                deptEntityIterator.remove();
//            }
//        }

        sysDeptEntityList.removeIf(deptEntity -> deptEntity.getDeptId().equals(deptId)
                || ArrayUtils.contains(StringUtils.split(deptEntity.getAncestors(), ","), deptId.toString()));
        return AjaxResult.success(entity2Vo(sysDeptEntityList));
    }


    /**
     * 根据部门编号获取详细信息
     */
    @RequiresPermissions("system:dept:query")
    @GetMapping(value = "/{deptId}")
    @DataScope
    public AjaxResult getInfo(@PathVariable Long deptId) {
        return AjaxResult.success(entity2Vo(sysDeptService.getDeptUnderScope(deptId)));
    }

    /**
     * 构建所有部门的下拉树形结构
     */
    @RequestMapping("/treeselect")
    @DataScope
    public AjaxResult treeselect(SysDept sysDept) {
        List<SysDeptEntity> sysDeptEntityList = sysDeptService.selectDeptList(sysDept);
        List<TreeSelect> deptVoTree = sysDeptService.buildDeptTreeSelect(entity2Vo(sysDeptEntityList));
        return AjaxResult.success(deptVoTree);
    }

    /**
     * 加载对应角色部门列表树
     */
    @RequestMapping(value = "/roleDeptTreeselect/{roleId}")
    @DataScope
    public AjaxResult roleDeptTreeselect(@PathVariable("roleId") Long roleId) {
        if (!SecurityUtils.getLoginUser().getRoleIds().contains(roleId)) {
            return AjaxResult.error("你无权限访问id为'" + roleId + "'的角色信息");
        }
        List<SysDeptEntity> sysDeptEntityList = sysDeptService.selectDeptList(new SysDept());
        AjaxResult ajax = AjaxResult.success();
        ajax.put("checkedKeys", sysDeptService.selectDeptListByRoleId(roleId));
        ajax.put("depts", sysDeptService.buildDeptTreeSelect(entity2Vo(sysDeptEntityList)));
        return ajax;
    }


    /**
     * 新增部门
     */
    @RequiresPermissions("system:dept:add")
    @Log(title = "部门管理", businessType = BusinessType.INSERT)
    @PostMapping
    @DataScope
    public AjaxResult add(@Validated @RequestBody SysDept sysDept) {
        // 权限校验
        List<Long> deptIds = SecurityUtils.getLoginUser().getAllowedDeptIds();
        if (StringUtils.isNotEmpty(deptIds) && !deptIds.contains(sysDept.getParentId())) {
            return AjaxResult.error("您没有权限向id为'" + sysDept.getParentId() + "'的部门中添加子部门");
        }

        if (sysDeptService.checkDeptNameUnique(sysDept)) {
            return AjaxResult.error("新增部门'" + sysDept.getDeptName() + "'失败，部门名称已存在");
        }

        sysDept.setCreateBy(SecurityUtils.getUserName());
        return toAjax(sysDeptService.addUnderParentStatus(vo2Entity(sysDept)));
    }

    /**
     * 修改
     */
    @RequiresPermissions("system:dept:edit")
    @Log(title = "部门管理", businessType = BusinessType.UPDATE)
    @PutMapping
    @DataScope
    public AjaxResult edit(@Validated @RequestBody SysDept sysDept) {
        // 权限校验
        List<Long> deptIds = SecurityUtils.getLoginUser().getAllowedDeptIds();
        if (StringUtils.isNotEmpty(deptIds) && !deptIds.contains(sysDept.getDeptId())) {
            return AjaxResult.error("您没有权限修改该部门的信息");
        }

        if (sysDeptService.checkDeptNameUnique(sysDept)) {
            return AjaxResult.error("修改部门'" + sysDept.getDeptName() + "'失败，部门名称已存在");
        } else if (sysDept.getParentId().equals(sysDept.getDeptId())) {
            return AjaxResult.error("修改部门'" + sysDept.getDeptName() + "'失败，上级部门不能是自己");
        } else if (StringUtils.equals(UserConstants.DEPT_DISABLE, sysDept.getStatus()) &&
                sysDeptService.countChildrenDeptById(sysDept.getDeptId(), UserConstants.DEPT_NORMAL) > 0) {
            return AjaxResult.error("该部门包含至少一个未停用的子部门！");
        }

        sysDept.setUpdateBy(SecurityUtils.getUserName());
        return toAjax(sysDeptService.updateById(vo2Entity(sysDept)));
    }

    /**
     * 删除部门
     */
    @RequiresPermissions("system:dept:remove")
    @Log(title = "部门管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{deptId}")
    public AjaxResult remove(@PathVariable("deptId") Long deptId) {
        // 权限校验
        List<Long> deptIds = SecurityUtils.getLoginUser().getAllowedDeptIds();
        if (StringUtils.isNotEmpty(deptIds) && !deptIds.contains(deptId)) {
            return AjaxResult.error("您没有权限修改该部门的信息");
        }

        if (sysDeptService.countChildrenDeptById(deptId, UserConstants.DEPT_NORMAL) > 0) {
            return AjaxResult.error("该部门存在至少一个未停用的子部门,不允许删除");
        }

        if (sysDeptService.countDeptExistUser(deptId, UserConstants.USER_NORMAL) > 0) {
            return AjaxResult.error("该部门存在至少一个未停用的用户,不允许删除");
        }

        // return toAjax(sysDeptService.deleteDeptById(deptId));
        return toAjax(sysDeptService.removeById(deptId));
    }

    /**
     * Entity 和 Vo类的转换
     */
    private List<SysDept> entity2Vo(List<SysDeptEntity> sysDeptEntityList) {
        return
                sysDeptEntityList.stream().map(sysDeptEntity -> {
                    SysDept sysDept = new SysDept();
                    BeanUtils.copyProperties(sysDeptEntity, sysDept);
                    return sysDept;
                }).collect(Collectors.toList());
    }

    private SysDept entity2Vo(SysDeptEntity sysDeptEntity) {
        SysDept sysDept = new SysDept();
        BeanUtils.copyProperties(sysDeptEntity, sysDept);
        return sysDept;
    }

    private List<SysDeptEntity> vo2Entity(List<SysDept> sysConfigList) {
        return
                sysConfigList.stream().map(sysDept -> {
                    SysDeptEntity sysDeptEntity = new SysDeptEntity();
                    BeanUtils.copyProperties(sysDept, sysDeptEntity);
                    return sysDeptEntity;
                }).collect(Collectors.toList());
    }

    private SysDeptEntity vo2Entity(SysDept sysDept) {
        SysDeptEntity sysDeptEntity = new SysDeptEntity();
        BeanUtils.copyProperties(sysDept, sysDeptEntity);
        return sysDeptEntity;
    }
}
